package com.hrsaas.ext.spider.core.url;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.hrsaas.ext.spider.util.Assert;

/**
 * <p>
 * 功能：分析导入的url并进行分解，转换成标准URL对象
 * <p>
 * 
 * @author wangxiaoliang@kanzhun.com
 *
 *         2018年8月1日
 */
public final class URLParser {

	private static final Pattern PROTOCOL_SPLIT = Pattern.compile("(.*?)://(.*)");
	private static final Pattern SLASH_SPLIT = Pattern.compile("(.*?)/(.*)");
	private static final Pattern PARAMS_SPLIT = Pattern.compile("(.*?)\\?(.*)");
	private static final Pattern HOST_PORT_SPLIT = Pattern.compile("(.*?)\\:(\\d*)");

	private static final Pattern PARAMETER_ELEMENT_SPLIT = Pattern.compile("(.*?)[\\;\\&$]");

	/**
	 * 分析导入的url并进行分解，转换成标准URL对象
	 * @return
	 */
	public static URL getURL(String url) {
		Assert.notNull("url", url);
		String protocol = null;
		Matcher m = PROTOCOL_SPLIT.matcher(url);
		String remainder;
		String u = url.toString();
		String host = null;
		if (m.find()) {
			protocol = m.group(1);
			remainder = m.group(2);
		} else {
			remainder = u;
		}
		if (protocol != null && protocol.trim().length() == 0) {
			protocol = null;
		}

		if (host == null) {
			m = SLASH_SPLIT.matcher(remainder);
			if (m.find()) {
				host = m.group(1);
				remainder = m.group(2);
			} else {
				host = remainder;
				remainder = null;
			}
		}

		int port = -1;
		if (protocol == null) {
			m = HOST_PORT_SPLIT.matcher(host);
			if (m.lookingAt()) {
				host = m.group(1);
				if (m.groupCount() > 1) {
					port = Short.valueOf(m.group(2));
				} else {
					port = -1;
				}
			}
		}

		if (remainder == null) {
			Protocol prot = protocol == null ? null : Protocol.forName(protocol);
			port = prot.getDefaultPort();
			return new URL(prot, host, port, null, null);
		}

		Parameters parameterSet = null;
		String path = null;
		String parameters = null;

		List<ParametersElement> params = new ArrayList<ParametersElement>();
		m = PARAMS_SPLIT.matcher(remainder);
		if (m.find()) {
			path = URLBuilder.unescape(m.group(1));
			parameters = m.group(2);
		} else {
			if (remainder.contains("=")) {
				parameters = remainder;
			} else {
				path = URLBuilder.unescape(remainder);
				if (path.isEmpty()) {
					path = "/";
				}
			}
		}
		
		if (!path.startsWith("/"))
			path = "/".concat(path);
		
		ParametersDelimiter delim = ParametersDelimiter.AMPERSAND;
		if (parameters != null) {
			delim = processParameters(params, parameters);
		}
		parameterSet = params.isEmpty() ? parameters == null ? null : ParsedParameters.parse(parameters)
				: new ParsedParameters(delim, params.toArray(new ParametersElement[params.size()]));

		Protocol proto = protocol == null ? Protocol.HTTP : Protocol.forName(protocol);
		port = port != -1 ? port : proto.getDefaultPort();
		URL result = new URL(proto, host, port, path, parameterSet);
		return result;
	}

	/**
	 * 请求参数分析
	 * @param l
	 * @param parameters
	 * @return
	 */
	private static ParametersDelimiter processParameters(List<ParametersElement> l, String parameters) {
		Matcher m = PARAMETER_ELEMENT_SPLIT.matcher(parameters);
		boolean match = m.find();
		ParametersDelimiter result = parameters.indexOf(ParametersDelimiter.AMPERSAND.charValue()) >= 0
				? ParametersDelimiter.AMPERSAND
				: ParametersDelimiter.SEMICOLON;
		if (match) {
			do {
				l.add(ParametersElement.parse(m.group(1)));
				int end = m.end(1);
				match = m.find();
				if (!match && end != parameters.length() - 1) {
					String rem = parameters.substring(end + 1);
					l.add(ParametersElement.parse(rem));
				}
			} while (match);
		}
		for (int i = parameters.length() - 1; i > 0; i--) {
			if (result.charValue() == parameters.charAt(i)) {
				l.add(ParametersElement.EMPTY);
			} else {
				break;
			}
		}
		return result;
	}
}
